/* 
 * File:   server.cpp
 * Author: zhouxich
 * Description: 服务器的main主线程，创建子线程并处理accept并将已连接描述符add到
 * 各个epoll_loop的监听事件中,这样就没有惊群问题
 */
#include "server.h"
using namespace std;

int sockfd;
event_base* base[NTHREAD];
task_handler handler;
map<int, bool> fd_alive;

int
main(int argc, char** argv){

	struct sockaddr_storage cliaddr;
	socklen_t len;
	int n;
	if (argc == 2)
	  sockfd = tcp_listen(NULL, argv[1], NULL);
	else if (argc == 3)
	  sockfd = tcp_listen(argv[1], argv[2], NULL);
	else {
		cout << "usage: server [ <host> ] <service or port>" << endl;
		exit(1);
	}

	/*初始化任务队列*/
	task_init(&handler, 100000);

	for(int i = 0; i < NWORKER; ++i)
		worker_make();

	for(int i = 0; i < NTHREAD; ++i)
		thread_make(i);

	int fd;
	int count = 0;
	for(;;){
		count %= NTHREAD;
		/*接受连接*/
		if ((fd = accept(sockfd, NULL, NULL)) < 0){
			if (errno == EINTR)
				continue;
			else{
				cout << "accept error: " << strerror(errno) << endl;
				continue;
			}
		}
	
		/*设置为非阻塞模式*/
		evutil_make_socket_nonblocking(fd);

		struct bufferevent* bev = NULL;

		/*新建bufferevent*/
		bev = bufferevent_socket_new(base[count], fd, BEV_OPT_CLOSE_ON_FREE);

		/*新建bufferevent出错*/
		if (NULL == bev){
			cout <<  "bufferevent socket new error" << endl;
			close(fd);		// 关闭套接字
			continue;
		}

		/*设置事件的回调函数*/
		bufferevent_setcb(bev, on_read, NULL, eventcb, bev);

		/*如果enable一个bufferevent出错，则直接返回*/
		if (bufferevent_enable(bev, EV_READ|EV_WRITE) < 0){
			cout << "bufferevent enable error" <<  endl;
			close(fd);		// 关闭套接字
			continue;
		}

		/*对output buffer加锁，有多线程访问*/
		int temp = evbuffer_enable_locking(bufferevent_get_output(bev), NULL);
		if (temp < 0)
			cout << "enable locking error" << endl;
		++count;
	}
		return 0;
}
